#ifndef _RING_QUEUE_HPP_
#define _RING_QUEUE_HPP_

#include <iostream>
#include <vector>
#include <pthread.h>
#include "sem.hpp"

const int DefaultCapacity = 5;

template <class T>
class RingQueue
{
public:
    RingQueue(int cap = DefaultCapacity)
        : _rq(cap)
        , _cap(cap)
        , _p_pos(0)
        , _c_pos(0)
        , _space_sem(cap)
        , _data_sem(0)
    {
        pthread_mutex_init(&_plock, nullptr);
        pthread_mutex_init(&_clock, nullptr);
    }

    ~RingQueue()
    {
        pthread_mutex_destroy(&_plock);
        pthread_mutex_destroy(&_clock);
    }

    // 生产数据(生产者调用)
    void Push(const T& in)
    {
        // 先申请信号量：先将资源分发给线程
        _space_sem.P();
        pthread_mutex_lock(&_plock);
        // 一定是竞争成功的生产者线程 -- 就一个！
        _rq[_p_pos++] = in;
        _p_pos %= _cap;
        pthread_mutex_unlock(&_plock);
        _data_sem.V();
    }

    // 消费数据(消费者调用)
    void Pop(T& out)
    {
        _data_sem.P();
        pthread_mutex_lock(&_clock);
        // 一定是竞争成功的消费者线程 -- 就一个！
        out = _rq[_c_pos++];
        _c_pos %= _cap;
        pthread_mutex_unlock(&_clock);
        _space_sem.V();
    }

private:
    std::vector<T> _rq;
    int _cap;
    int _p_pos; // 生产位置
    int _c_pos; // 消费位置
    Sem _space_sem; // 空间资源
    Sem _data_sem;  // 数据资源
    pthread_mutex_t _plock;
    pthread_mutex_t _clock;
};

#endif